/*
    job8/pp.c: 使用条件变量实现 ping-pong 问题

    + 系统中有2个线程：ping 线程和 pong 线程
    + ping 线程先执行
    + ping 线程执行流程如下
    1. 打印输出 ping
    2. 等待 pong 线程输出
    3. 执行第 1 步
    + pong 线程执行流程如下
    1. 打印输出 pong
    2. 等待 ping 线程输出
    3. 执行第 1 步
    + 程序输出结果
    ping
    pong
    ping
    pong
    ...
*/
 
/*
    互斥关系：现在该输出什么，1个
    同步关系：ping->pong->ping...，2个
*/

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

#define COUNT 5

int now_is_ping = 1;
pthread_mutex_t mutex;
pthread_cond_t last_is_ping, last_is_pong;

void *ping(void *arg) {
    int i;
    for(i = 0; i < COUNT; i ++) {
        pthread_mutex_lock(&mutex);
        while(!now_is_ping)
            pthread_cond_wait(&last_is_pong, &mutex);
        printf("ping\n");
        now_is_ping = 0;
        pthread_cond_signal(&last_is_ping);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

void *pong(void *arg) {
    int i;
    for(i = 0; i < COUNT; i ++) {
        pthread_mutex_lock(&mutex);
        while(now_is_ping)
            pthread_cond_wait(&last_is_ping, &mutex);
        printf("pong\n");
        now_is_ping = 1;
        pthread_cond_signal(&last_is_pong);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main() {
    pthread_t ping_tid, pong_tid;

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&last_is_ping, NULL);
    pthread_cond_init(&last_is_pong, NULL);

    pthread_create(&ping_tid, NULL, ping, NULL);
    pthread_create(&pong_tid, NULL, pong, NULL);

    pthread_join(ping_tid, NULL);
    pthread_join(pong_tid, NULL);

    return 0;
}